package com.threeti.mecool.core.util;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.acls.domain.DefaultPermissionFactory;
import org.springframework.security.acls.domain.PermissionFactory;
import org.springframework.security.acls.model.Permission;
import org.springframework.security.core.Authentication;
import org.springframework.util.CollectionUtils;

import com.threeti.mecool.core.application.acl.UserAdapter;
import com.threeti.mecool.core.domain.model.acl.PermissionConst;
import com.threeti.mecool.core.domain.model.acl.User;
import com.threeti.mecool.core.infrastructure.persistence.acl.UserRepository;

/**
 * TODO jay:cache
 */
public class MyAclPermissionEvaluator implements PermissionEvaluator {
	private UserRepository userRepository;
	
  private PermissionFactory permissionFactory = new DefaultPermissionFactory();

	public MyAclPermissionEvaluator(UserRepository userRepository) {
		super();
		this.userRepository = userRepository;
	}

	@Override
	public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
		return false;
	}

	public boolean hasPermission(String userloginName, Serializable targetId, String targetType, Object permission) {		
		User targetUser = userRepository.findWithPermissionRoleAndEntries(userloginName);
		if (targetUser.getPermissionRole() == null) return false;
		if (CollectionUtils.isEmpty(targetUser.getPermissionRole().getPermissionEntries())) return false;
		
		List<Permission> perms = resolvePermission(permission);
		
		int mask = perms.get(0).getMask();
		String secureEntry = targetId + PermissionConst.P_MOUDLE_ID_SEPARATOR + targetType + PermissionConst.P_MOUDLE_ID_SEPARATOR + mask;
		
		return targetUser.getPermissionRole().getPermissionEntries().contains(secureEntry);
	}

	@Override
	public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
		if (authentication.getPrincipal() == null) return false;
		String loginName = ((UserAdapter)authentication.getPrincipal()).getUsername();
		
		return hasPermission(loginName, targetId, targetType, permission);
	}

  List<Permission> resolvePermission(Object permission) {
      if (permission instanceof Integer) {
          return Arrays.asList(permissionFactory.buildFromMask(((Integer)permission).intValue()));
      }

      if (permission instanceof Permission) {
          return Arrays.asList((Permission)permission);
      }

      if (permission instanceof Permission[]) {
          return Arrays.asList((Permission[])permission);
      }

      if (permission instanceof String) {
          String permString = (String)permission;
          Permission p;

          try {
              p = permissionFactory.buildFromName(permString);
          } catch(IllegalArgumentException notfound) {
              p = permissionFactory.buildFromName(permString.toUpperCase());
          }

          if (p != null) {
              return Arrays.asList(p);
          }

      }
      throw new IllegalArgumentException("Unsupported permission: " + permission);
  }

	public MyAclPermissionEvaluator() {
		super();
		// TODO Auto-generated constructor stub
	}
  
  

}
